﻿using Newtonsoft.Json;
using OSGeo.GDAL;
using OSGeo.OGR;
using RemoteSensingImageDirectServer.Models.Map.Cache;
using RemoteSensingImageDirectServer.Models.Map.Register;
using RemoteSensingImageDirectServer.Models.Storage;
using RemoteSensingImageDirectServer.Untils.Extensions;
using RemoteSensingImageDirectServer.Untils.ScopeSpace;

namespace RemoteSensingImageDirectServer.Untils.Source
{
    public class GroupImageSource : IRSIGroupImageSource, IRSIMapSource
    {
        /// <summary>
        /// 资源是否被释放
        /// </summary>
        private bool _disposed;

        /// <summary>
        /// 图层的json文件配置
        /// </summary>
        private readonly GroupImageCache GroupImage;

        /// <summary>
        /// 图层的掩膜文件路径
        /// </summary>
        private readonly string MaskFilename;

        /// <summary>
        /// 图层的主键
        /// </summary>
        private readonly string Key;

        /// <summary>
        /// 掩膜文件的数据源
        /// </summary>
        private readonly DataSource MaskDatasource;

        /// <summary>
        /// 是否正常初始化
        /// </summary>
        private readonly bool IsValid = false;

        /// <summary>
        /// 联合图层配置信息
        /// </summary>
        private readonly GroupMapConfiger MapConfiger;

        /// <summary>
        /// 图层数据
        /// </summary>
        private Dataset DstDataset { get; set; }

        /// <summary>
        /// 数据的坐标系六参数
        /// </summary>
        private RasterEnvelope DstRasterEnvelope { get; set; }

        /// <summary>
        /// 图层的缩略图层源数据
        /// </summary>
        private IRSIMapSource RSITbnDataset { get; set; }


        public GroupImageSource(string key, GroupImageCache groupImage)
        {
            Key = key;
            GroupImage = groupImage;
            MapConfiger = JsonConvert.DeserializeObject<GroupMapConfiger>(GroupImage.MapConfig);
            IsValid = InitDstDataset();
        }

        private bool InitDstDataset()
        {
            if (MapConfiger.Properties.SaveType == 0)
            {
                var localStorage = (GroupImageStorage)MapConfiger.Properties.Storage;
                var key = localStorage.ThumbnailPath + "_0".ToMD5String();
                DstDataset = Gdal.OpenShared(localStorage.DataSourcePath, Access.GA_Update);
                RSITbnDataset = new SingleImageSource(key, localStorage.ThumbnailPath, 0);
            }
            else
            {
                foreach (var groupWarpItem in GroupImage.GroupImageWarps)
                {
                    var vsiWarpName = string.Format("/vsimem/{0}_warp_{1}.vrt", groupWarpItem.Key, MapConfiger.EPSG);
                    Gdal.FileFromMemBuffer(vsiWarpName, groupWarpItem.WarpData);
                }

                var vsiVrtName = string.Format("/vsimem/{0}.vrt", Key);
                Gdal.FileFromMemBuffer(vsiVrtName, GroupImage.VrtData);

                DstDataset = Gdal.OpenShared(vsiVrtName, Access.GA_Update);
            }
            return true;
        }

        public string GetKey()
        {
           return this.Key;
        }

        public int GetDstEPSG()
        {
            return this.MapConfiger.EPSG;
        }
        public GroupMapConfiger GetMapConfiger()
        {
            return this.MapConfiger;
        }

        public RasterEnvelope GetBoundbox()
        {
            return this.MapConfiger.BoundBox;
        }

        public RasterEnvelope GetLatLonBoundbox()
        {
            return this.MapConfiger.LatLonBoundingBox;
        }

        public Dataset GetDstDataset()
        {
            return this.DstDataset;
        }

        public RasterEnvelope GetDstRasterEnvelope()
        {
            return this.DstRasterEnvelope ??= this.DstDataset.GetRasterEnvelope();
        }

        public DataSource GetMaskDataSource()
        {
            return this.MaskDatasource;
        }

        public string GetMaskFilename()
        {
            return this.MaskFilename;
        }

        public IRSIMapSource GetThumbnail()
        {
            return this.RSITbnDataset;
        }

        public bool Valid()
        {
            return this.IsValid;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }


        protected virtual void Dispose(bool disposing)
        {
            if (!this._disposed)
            {
                if (disposing)
                {
                    DstDataset?.Free();

                    DstRasterEnvelope?.Dispose();

                    if (RSITbnDataset is SingleImageSource singleImaegNode)
                    {
                        singleImaegNode.Dispose();
                    }

                    MaskDatasource?.Free();

                    foreach (var groupWarpItem in GroupImage.GroupImageWarps)
                    {
                        var vsiWarpName = string.Format("/vsimem/{0}_warp_{1}.vrt", groupWarpItem.Key, MapConfiger.EPSG);
                        Gdal.Unlink(vsiWarpName);
                    }

                    var vsiVrtName = string.Format("/vsimem/{0}.vrt", Key);
                    Gdal.Unlink(vsiVrtName);
                }

                this._disposed = true;
            }
            else
            {
                throw new Exception("资源已被释放");
            }
        }


        ~GroupImageSource()
        {
            Dispose(false);
        }
    }
}
